package com.vishudha.timer.task;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.vishudha.timer.VishudhaHelper;
import com.vishudha.timer.domain.VishudhaAlert;
import com.vishudha.timer.domain.VishudhaTimeType;
import com.vishudha.timer.event.VishudhaEvent;
import com.vishudha.timer.event.VishudhaEventType;
import com.vishudha.timer.listner.VishudhaListner;

public abstract class VishudhaTask extends TimerTask {
	private Timer timer;
	private long time;
	private long delay;
	private VishudhaAlert alert;
	private VishudhaTimeType timeType;
	private List<VishudhaListner <VishudhaTask>> listners;
	
	public VishudhaTask(long time, VishudhaAlert alert) {
		this(time, alert, VishudhaTimeType.TENTH_OF_A_SECONDS);
	}
	
	public VishudhaTask(long time, VishudhaAlert alert, VishudhaTimeType timeType) {
		timer = new Timer();
		listners = new ArrayList<VishudhaListner<VishudhaTask>>();
		
		setTimeType(timeType);
		setTime(time);
		setAlert(alert);
		setDelay(timeType.getDefaultInterval());
	}
	
	//Abstract Methods
	protected abstract void raiseEvent(VishudhaEvent<VishudhaTask> event);

	/**
	 * Method to execute task at fixed rate
	 */
	public void executeTask(){
		timer.scheduleAtFixedRate(this, delay, timeType.getDefaultInterval());
		raiseEvent(new VishudhaEvent<VishudhaTask>(time, this, VishudhaEventType.START));
	}

	public void run() {
		raiseEvent(new VishudhaEvent<VishudhaTask>(time, this, VishudhaEventType.UPDATE));
		
		if( time <= 1) { 
			timer.cancel();
			raiseEvent(new VishudhaEvent<VishudhaTask>(time, this, VishudhaEventType.END));
		} else if (alert.isAlertAllowed(time)) {
			raiseEvent(new VishudhaEvent<VishudhaTask>(time, this, VishudhaEventType.ALERT));
		}
		time = VishudhaHelper.reduceTimeIntervel(time, timeType);
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		if (time <= 0)
			throw new IllegalArgumentException("Interval/Time can not be zero or nagitive, Please provide positive value");

		this.time = time;
	}

	public long getDelay() {
		return delay;
	}

	public void setDelay(long delay) {
		if(delay <= 0)
			throw new IllegalArgumentException("Delay can not be zero or nagitive, Please provide positive value");
		this.delay = delay;
	}

	public VishudhaAlert getAlert() {
		return alert;
	}

	public void setAlert(VishudhaAlert alert) {
		if(alert.isValid())
			this.alert = alert;
	}

	public VishudhaTimeType getTimeType() {
		return timeType;
	}

	public void setTimeType(VishudhaTimeType timeType) {
		if(timeType == null)
			throw new IllegalArgumentException("Time Type can not be Null, Please provide a valid value");
		this.timeType = timeType;
	}

	protected List<VishudhaListner<VishudhaTask>> getListners() {
		return listners;
	}

	public void addListner(VishudhaListner<VishudhaTask> listner) {
		this.listners.add(listner);
	}
	
	public void removeListner(VishudhaListner<VishudhaTask> listner) {
		this.listners.remove(listner);
	}
}
